package com.dh.leetcode.five;

import org.junit.Assert;
import org.junit.Test;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * @ClassName: _576_relative_ranks
 * @Description: 506. 相对名次
 * 给你一个长度为 n 的整数数组 score ，其中 score[i] 是第 i 位运动员在比赛中的得分。所有得分都 互不相同 。
 * <p>
 * 运动员将根据得分 决定名次 ，其中名次第 1 的运动员得分最高，名次第 2 的运动员得分第 2 高，依此类推。运动员的名次决定了他们的获奖情况：
 * <p>
 * 名次第 1 的运动员获金牌 "Gold Medal" 。
 * 名次第 2 的运动员获银牌 "Silver Medal" 。
 * 名次第 3 的运动员获铜牌 "Bronze Medal" 。
 * 从名次第 4 到第 n 的运动员，只能获得他们的名次编号（即，名次第 x 的运动员获得编号 "x"）。
 * 使用长度为 n 的数组 answer 返回获奖，其中 answer[i] 是第 i 位运动员的获奖情况。
 * <p>
 * <p>
 * <p>
 * 示例 1：
 * <p>
 * 输入：score = [5,4,3,2,1]
 * 输出：["Gold Medal","Silver Medal","Bronze Medal","4","5"]
 * 解释：名次为 [1st, 2nd, 3rd, 4th, 5th] 。
 * 示例 2：
 * <p>
 * 输入：score = [10,3,8,9,4]
 * 输出：["Gold Medal","5","Bronze Medal","Silver Medal","4"]
 * 解释：名次为 [1st, 5th, 3rd, 2nd, 4th] 。
 * <p>
 * 提示：
 * <p>
 * n == score.length
 * 1 <= n <= 10^4
 * 0 <= score[i] <= 10^6
 * score 中的所有值 互不相同
 * <p>
 * https://leetcode-cn.com/problems/relative-ranks/
 * @Author: shouzimu
 * @Date: 2021/12/2 9:06
 */
public class _576_relative_ranks {
    static Map<Integer, String> map = new HashMap<>();

    static {
        map.put(1, "Gold Medal");
        map.put(2, "Silver Medal");
        map.put(3, "Bronze Medal");
    }


    /**
     * 二维记录下标，性能一般
     *
     * @param nums
     * @return
     */
    public String[] findRelativeRanks2(int[] nums) {
        int len = nums.length;
        int[][] array = new int[len][2];
        for (int i = 0; i < len; i++) {
            array[i][0] = nums[i];
            array[i][1] = i;
        }
        Arrays.sort(array, (o1, o2) -> o2[0] - o1[0]);
        String[] res = new String[len];
        int index = 0;
        for (int[] ints : array) {
            index++;
            int v = ints[1];
            String value;
            if (index < 4) {
                value = map.get(index);
            } else {
                value = String.valueOf(index);
            }
            res[v] = value;
        }
        return res;
    }

    /**
     * 使用桶的方式，先找出最大的值作为桶
     * 一开始写死了性能较差
     * @param nums
     * @return
     */
    public String[] findRelativeRanks(int[] nums) {
        int maxScore = 0;
        for (int num : nums) {
            if (num > maxScore) {
                maxScore = num;
            }
        }
        int len = maxScore + 1;
        int[] scores = new int[len];
        for (int i = 0; i < nums.length; i++) {
            scores[nums[i]] = i + 1;
        }

        String[] res = new String[nums.length];
        int index = 0;
        for (int i = 0; i < scores.length; i++) {
            int j = len - i - 1;
            int v = scores[j];
            if (v > 0) {
                index++;
                String value;
                if (index < 4) {
                    value = map.get(index);
                } else {
                    value = String.valueOf(index);
                }
                res[v - 1] = value;
            }
        }
        return res;
    }

    @Test
    public void findRelativeRanksTest() {

        Assert.assertEquals(Arrays.toString(new String[]{"Bronze Medal", "Silver Medal", "Gold Medal"}),
                Arrays.toString(findRelativeRanks(new int[]{100, 101, 111111})));


        Assert.assertEquals(Arrays.toString(new String[]{"Gold Medal", "5", "Bronze Medal", "Silver Medal", "4"}),
                Arrays.toString(findRelativeRanks(new int[]{10, 3, 8, 9, 4})));

        Assert.assertEquals(Arrays.toString(new String[]{"Gold Medal", "Silver Medal", "Bronze Medal", "4", "5", "6"}),
                Arrays.toString(findRelativeRanks(new int[]{5, 4, 3, 2, 1, 0})));
    }
}
